package dS.ProjectGPS.LeicaOWI;

import dS.ProjectGPS.GPS.*;
import dS.ProjectGPS.Bluetooth.*;
import dS.ProjectGPS.LeicaOWI.*;
import java.io.*;
import javax.microedition.lcdui.*;
import dS.ProjectGPS.StringTokenizer;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>@author David So</p>
 *
 * @version 1.0
 */
public class OWIAgent {

  private static Controller controller;
  private static Display display;

  boolean streamsSet = false;
  public InputStream in = null;
  public PrintStream out = null;

  public static MessageUI debug = new MessageUI();

  boolean running = false;

  public OWIAgent(Controller c, Display d) {
    controller = c;
    display = d;

    debug.setCommandListener(controller);
    debug.add("- Controller Created -");
  }

  public void togglePower(){
   /* if(in == null || out == null){
      Alert alert = new Alert("Controller", "Bluetooth device not connected", null,
                        AlertType.INFO);
      alert.setTimeout(3000);
      display.setCurrent(alert, ProjectGPSme.mainMenu);

    }
    else { */
      if (OWI.power) {
        sendMessage("$PLEIS,PWR,0*");
        OWI.power = false; // Modify later - use ACK received
      }
      else {
        sendMessage("$PLEIS,PWR,1*");
        OWI.power = true;
      }
  //  }
  }

  public void query(String msg){
    //display.setCurrent(debug);
    //debug.add(msg);
    sendMessage(msg);

    // Wait 1s for reply
    try {
      Thread.currentThread().sleep(1000);
    } catch (Exception e){
       debug.add("Couldn't Sleep");
    }

    // No separate ACK since immediate output
    String temp = readLine();
    //debug.add(temp);

    new OWI(temp);
  }

  /**
   * Send Query for NMEA GSV Sentence
   */
  public void queryGSV(){
    sendMessage(OWI.standardQueryMessage("GSV", "0", "200"));

    //display.setCurrent(debug);

    // Wait 1s for reply
    try {
      Thread.currentThread().sleep(1000);
    }
    catch (Exception e) {
      debug.add("Couldn't Sleep");
    }

    OWI.clearGSV();

    // No separate ACK since immediate output
    String temp = readLine();
    //debug.add(temp);

    new OWI(temp);

    for(int i = NMEA.currentMsg; i < NMEA.numMsg; i++){
      temp = readLine();
      //debug.add(temp);
      new OWI(temp);
    }
  }

  public void showDebug(){
    display.setCurrent(debug);
  }


  /**
   * Sends given OWI SET message then checks and compares sensor for correct
   * ACK reply
   *
   * @param msg String
   * @param msgId String
   * @return boolean
   */
  public int set(String msgId, String msg) {
    display.setCurrent(debug);
    debug.add(msg);
    sendMessage(msg);

    // Wait 1s for reply
    try {
      Thread.currentThread().sleep(1000);
    }
    catch (Exception e) {
      debug.add("Couldn't Sleep");
    }

    // Check ACK reply
    String temp = readLine();
    debug.add(temp);
    return getACK(msgId, temp);
  }

  /**
   * Checks if ACK reply is valid
   *
   * @param id String
   * @param ack String
   * @return boolean
   */
  private boolean checkACK(String id, String ack){
    if(ack.startsWith("$PLEIR,ACK,"+id+",0")){
      return true;
    } else {
      return false;
    }
  }

  private int getACK(String id, String ack){
    try{
      String[] ackTokens = StringTokenizer.tokenizeString(ack, ",");
      return Integer.parseInt(NMEA.removeChecksum(ackTokens[3]));
    } catch (Exception e){
      // Do nothing
      return 6;
    }
  }


  /**
   * Reads and returns the next sentence from serial port
   *
   * @return String
   */
  private String readLine() {
    String answer = "";

    int ch = 0;

    try {
      while ((ch = in.read()) != '\n') {
        if(ch != -1){
          answer += (char)ch;
        }
      }
      answer += '\n';
    }
    catch (Exception e) {
      display.setCurrent(debug);
      debug.add("Could not get line" + e);
    }

    //debug.add("answer = " + answer);
    return answer;
  }



  /**
   * Sends input string to output serial port
   *
   * @param raw String
   */
  private void sendMessage(String raw){
    out.println(raw + checksum(raw) + '\r');
    out.flush();
  }

  /**
   * Returns the XOR checksum of input sentence.
   * Input sentence must start with $ and end with *
   *
   * @param msg String
   * @return String
   */
  private static String checksum(String msg) {
    int checksum = 0;
    for (int i = 0; i < msg.length(); i++) {
      if (msg.charAt(i) == '$') {
        continue;
      }
      else if (msg.charAt(i) == '*') {
        break;
      }
      checksum ^= msg.charAt(i);
    }

    String answer = (Integer.toHexString(checksum)).toUpperCase();

    // Checksums must be of length 2
    if(answer.length() == 1){
      answer = "0" + answer;
    }
    return answer;
  }
}
